package com.hejing.解决单例模式中的懒汉式中的线程安全问题;

/**
 * ClassName: BankTestLanHan
 * Package: com.hejing.解单例模式中的懒汉模式中的线程安全问题
 * Description:
 * 使用同步机制解决单例模式中的懒汉式的线程安全问题
 *
 * @Author: HeJing
 * @Create: 2023-04-15 9:27
 * @Version: 1.0
 */
public class BankTestLanHan {

    static Bank b1 = null;
    static Bank b2 = null;

    public static void main(String[] args) {
        Thread t1 = new Thread() {
            @Override
            public void run() {
                b1 = Bank.getInstance();
            }
        };
        t1.setName("线程01");
        t1.start();

        Thread t2 = new Thread() {
            @Override
            public void run() {
                b2 = Bank.getInstance();
            }
        };
        t2.setName("线程02");
        t2.start();

        try {
            t1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        try {
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(b1);
        System.out.println(b2);
        System.out.println(b1 == b2);
    }
}


class Bank {

    // 提供私有构造器
    private Bank() {
    }

    private static volatile Bank instance = null;

    // 提供静态的对外构造实例的接口

    // 实现线程安全的方式1: 同步方法
//    public synchronized static Bank getInstance() {
//        try {
//            Thread.sleep(500);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//        if (instance == null) {
//            instance = new Bank();
//        }
//        return instance;
//    }

    // 实现线程安全的方式2: 同步代码块
//    public static Bank getInstance() {
//        try {
//            Thread.sleep(500);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//        synchronized(Bank.class) {
//            if (instance == null) {
//                instance = new Bank();
//            }
//            return instance;
//        }
//    }

    // 实现线程安全的方式3: 优化版本: 仔细揣摩
    // 相较于方式1 和 方式2 效率更高。
    // 为了避免出现指令重排，需要将 instance 声明为 volatile
    public static Bank getInstance() {
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if(instance == null) {
            synchronized(Bank.class) {
                if (instance == null) {
                    instance = new Bank();
                }
            }
        }
        return instance;
    }

}
























